import React, { useEffect, useRef, useState } from 'react';
import { Button, Tabs } from 'antd';
import { useMemoizedFn, useSize } from 'ahooks';
import { PlusOutlined } from '@ant-design/icons';
import { message } from '@tauri-apps/api/dialog';
import { getCommandKey, separator } from '@/utils';
import { openDevWeb, openVsCodeRun, stopProcess } from '@/services/command';

import Terminal from './Terminal';
import './index.less';

const { TabPane } = Tabs;

// 终端的和序号对应的映射
const terminalKeyIndexMap = new Map();

// 生成一个终端
function formatCommandTerminal(params: {
  commandLabel?: string;
  count?: number;
  code: string;
  command?: string;
  commandValue?: string;
  type: TerminalType; // 自定义命令/非指定终端
  workSpace?: string;
  closable?: boolean;
}): CommandTerminal {
  const {
    commandLabel,
    count,
    code,
    command,
    commandValue,
    type,
    workSpace,
    closable = true,
  } = params;
  const key = commandValue
    ? getCommandKey(code, commandValue)
    : `${code}${separator}${count}`;
  const title = commandLabel || `终端`;
  const comm = command || key;
  return {
    type,
    title,
    key,
    code, // 项目编码
    command: comm, // 执行命令
    rowNum: 0, // 日志已读行
    workSpace,
    closable,
  };
}

const maxTerminalCount = 5;

interface WorkerItemProps {
  data: WorkerData;
  code: string;
  onChange: (code: string, data: WorkerData) => void;
}
const WorkerItem: React.FC<WorkerItemProps> = (props) => {
  const { data, code, onChange } = props;

  // const cardRef = useRef<HTMLDivElement>(null);
  const btnsRef = useRef<HTMLDivElement>(null);
  const workerItemRef = useRef<HTMLDivElement>(null);
  const [activeKey, setActiveKey] = useState<string>();
  const [tabHeight, setTabHeight] = useState<number>();
  const [terminalHeight, setTerminalHeight] = useState<number>();
  const [terminalWidth, setTerminalWidth] = useState<number>();
  const bodySize = useSize(document.querySelector('body'));
  // const cardSize = useSize(cardRef);
  const btnsSize = useSize(btnsRef);
  const wrokerItemSize = useSize(workerItemRef);

  useEffect(() => {
    if (bodySize?.height) {
      const tabHeight = bodySize.height - 42;
      setTabHeight(tabHeight);
      if (btnsSize?.height) {
        const terminalHeight = tabHeight;
        setTerminalHeight(terminalHeight);
      }
      if (btnsSize?.width) {
        const terminalW = (wrokerItemSize?.width || 0) - btnsSize.width;
        setTerminalWidth(terminalW);
      }
    } else {
      setTabHeight(undefined);
    }
  }, [bodySize, btnsSize]);

  const { workSpace, commands, commandTerminals, devUrl } = data;

  const checkTabNum = useMemoizedFn(() => {
    if (
      Array.isArray(commandTerminals) &&
      commandTerminals?.length >= maxTerminalCount
    ) {
      message(`最多只能打开${maxTerminalCount}个终端`, {
        title: '提示',
        type: 'error',
      });
      return false;
    }
    return true;
  });
  // 打开vscode
  const openVsCode = useMemoizedFn(() => {
    openVsCodeRun(workSpace as string);
  });

  const execCommand = useMemoizedFn(
    (
      command: string,
      commandLabel: string,
      commandValue: string,
      closable?: boolean,
    ) => {
      const terminal = formatCommandTerminal({
        commandLabel,
        code,
        command,
        commandValue,
        type: 'COMMAND',
        workSpace,
        closable,
      });
      // 如果 终端不存在
      if (!terminalKeyIndexMap.has(terminal.key)) {
        // 如果终端的数量超过限制
        if (!checkTabNum()) return;
        const { commandTerminals = [] } = data;
        data.commandTerminals = [...commandTerminals, terminal];
        onChange(code, { ...data });
      }
      setActiveKey(terminal.key);
    },
  );

  const delTabPane = useMemoizedFn((key: any) => {
    stopProcess(key);
    if (!Array.isArray(commandTerminals)) return;
    const index = terminalKeyIndexMap.get(key);
    const nextIndex = Math.min(index + 1, (commandTerminals?.length || 0) - 2);
    const terminal = commandTerminals[nextIndex];
    const nextKey = terminal?.key;
    commandTerminals.splice(index, 1);
    data.commandTerminals = [...commandTerminals];
    onChange(code, { ...data });
    setActiveKey(nextKey);
  });

  const openDefaultTerminal = useMemoizedFn(() => {
    if (!commandTerminals?.length) {
      const defaultCommand = (commands || [])[0];
      if (defaultCommand) {
        const { command, label, value } = defaultCommand;
        execCommand(command, label, value, false);
      }
    } else {
      setActiveKey(commandTerminals[0].key);
    }
  });

  const addCommandTerminal = useMemoizedFn(() => {
    if (!checkTabNum()) return;
    let maxCount = 0;
    commandTerminals?.forEach((terminal) => {
      if (terminal.type === 'TERMINAL') {
        const [, count] = terminal.key?.split(separator);
        maxCount = Math.max(maxCount, Number(count));
      }
    });
    const newCount = maxCount + 1;
    const terminal = formatCommandTerminal({
      code,
      count: newCount,
      type: 'TERMINAL',
      workSpace,
    });
    data.commandTerminals = [...(commandTerminals || []), terminal];
    onChange(code, { ...data });
    setActiveKey(terminal.key);
  });

  const openDevUrl = useMemoizedFn(() => {
    if (!devUrl || !/^http/.test(devUrl)) {
      message('调试页面路径必须是以http/https开头的url路径', {
        title: '提示',
        type: 'error',
      });
    } else {
      openDevWeb(devUrl);
    }
  });

  useEffect(() => {
    terminalKeyIndexMap.clear();
    commandTerminals?.forEach((terminal, index) => {
      terminalKeyIndexMap.set(terminal.key, index);
    });
    openDefaultTerminal();
  }, [commandTerminals]);

  return (
    <div
      className="worker-item"
      style={{ height: tabHeight }}
      ref={workerItemRef}
    >
      <div style={{ height: terminalHeight }} className="tabs-wrapper">
        <div style={{ width: terminalWidth }} className="tabs-parent">
          <Tabs
            className="terminal-tabs"
            size="small"
            type="editable-card"
            hideAdd
            onEdit={delTabPane}
            activeKey={activeKey}
            onChange={setActiveKey}
          >
            {commandTerminals?.map(
              ({
                key,
                command,
                title,
                type,
                workSpace,
                closable,
              }: CommandTerminal) => (
                <TabPane
                  key={key}
                  tab={title}
                  closable={closable}
                  style={{ display: key !== activeKey ? 'none' : undefined }}
                >
                  <Terminal
                    height={terminalHeight}
                    type={type}
                    terminalkey={key}
                    command={command}
                    code={code}
                    workSpace={workSpace}
                  />
                </TabPane>
              ),
            )}
          </Tabs>
        </div>
        <div ref={btnsRef} className="worker-item-btns">
          <Button type="primary" onClick={addCommandTerminal}>
            <PlusOutlined />
          </Button>
          <Button type="primary" onClick={openVsCode}>
            打开VSCode
          </Button>
          {devUrl && (
            <Button type="primary" onClick={openDevUrl}>
              打开调试页面
            </Button>
          )}
          {commands?.map(({ label, value, command }) => (
            <Button
              type="primary"
              key={value}
              onClick={() => execCommand(command, label, value)}
            >
              {label}
            </Button>
          ))}
        </div>
      </div>
    </div>
  );
};

export default React.memo(WorkerItem);
